#include <string>
#include <png.h>
#include <chrono>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <stdexcept>
#include <glib.h>

#include <typeinfo>
#include <iostream>
#include <string>

#include "CameraController.h"
#include "../system/log.h"


namespace DataCollection{
    namespace Camera
    {
        CameraController::CameraController(std::string address)
        :image_saver("/home/gbl/data"){
            this->address = address;
            GError *error = NULL;

            // 连接相机
            if (address.empty())
                this->camera = arv_camera_new(NULL, &error);
            else
                this->camera = arv_camera_new(address.c_str(), &error);
            
            // 初始化相机错误
            if (!ARV_IS_CAMERA (this->camera)){
                LOG_ERROR(error->message);
                return ;
            }
            
            // 初始化相机成功
            LOG_INFO("connect camera IP[" , address, "]");

        }

        void CameraController::test_param(){
            GError *error = NULL;

            // 设置像素格式
            arv_camera_set_pixel_format(this->camera, ARV_PIXEL_FORMAT_RGB_8_PACKED, &error);
            if(error){
                LOG_ERROR(error->message);
                return ;
            }

            // 看查当前像素格式
            const char *pixel_format1 = arv_camera_get_pixel_format_as_string(this->camera, &error);
            if(error){
                LOG_ERROR(error->message);
                return ;
            }
            LOG_INFO("current pixel format [ ", pixel_format1, "]");


            // 设置曝光
            arv_camera_set_exposure_time(this->camera, 800000, &error);
            if(error){
                LOG_ERROR(error->message);
                return ;
            }
        }

        void CameraController::collection_single_frame(){
            ArvBuffer *buffer;
            GError *error;

            // 获取一帧图像
            buffer = arv_camera_acquisition(this->camera, 0, &error);

            if (ARV_IS_BUFFER(buffer)){
                std::stringstream ss1, ss2;
                int width = arv_buffer_get_image_width(buffer);
                int height = arv_buffer_get_image_height(buffer);

                ss1 << "width [" << width << "] ";
                ss2 << "height [" << height << "] ";
                LOG_INFO("get one fream data", ss1.str(), ss2.str());
                
                // 保存图像为PNG格式
                unsigned char* data_image = (unsigned char *)arv_buffer_get_image_data(buffer, NULL);
                std::time_t timestamp_collection = arv_buffer_get_timestamp(buffer);
                bool is_save_success = Image::ImageSaver("/home/gbl/data").save_image_as_png(data_image, timestamp_collection, width, height, 8, PNG_COLOR_TYPE_RGB);
                if (is_save_success)
                    LOG_INFO("save a PNG image success. path [/home/gbl/data]");
                else
                    LOG_ERROR("save a PNG image failed");
                
            }
            else{
                LOG_ERROR("collection fali! error:", error->message);
            }

            g_object_unref(buffer);
        }

        void CameraController::collection_voide(){
            GError* error;
            // 创建数据流
            ArvStream* stream_voide = arv_camera_create_stream(this->camera, NULL, NULL, &error);
            if (!ARV_IS_STREAM(stream_voide)){
                LOG_ERROR("Could not create voide stream (", error->message, ")");
                return ;
            }

            // 创建 buffer 存储视频流的数据
            for (int i=0; i<this->num_buffer; i++){
                arv_stream_push_buffer(stream_voide, arv_buffer_new(this->width * this->height * 3, NULL));
            }

            // 开始获取视频流
            error = nullptr;
            arv_camera_start_acquisition(this->camera, &error);
            if (error){
                LOG_ERROR("start cmaera failed");
                g_object_unref(stream_voide);
            }

            // 获取视频流并安间隔时间保存图像
            while(true){
                ArvBuffer* buffer = arv_stream_pop_buffer(stream_voide);
                if (buffer == nullptr || arv_buffer_get_status(buffer) != ARV_BUFFER_STATUS_SUCCESS) {
                    LOG_ERROR("get fream failed");
                    break;
                }

                // 获取图像尺寸和数据
                size_t width = arv_buffer_get_image_width(buffer);
                size_t height = arv_buffer_get_image_height(buffer);
                unsigned char* image_data = const_cast<unsigned char*>(static_cast<const unsigned char*>(arv_buffer_get_data(buffer, nullptr)));

                // 将 buffer 放回流中
                arv_stream_push_buffer(stream_voide, buffer);

                if (image_data == nullptr) {
                    LOG_WARNING("get frame fail");
                    continue;
                }

                // 传输视频
                LOG_INFO("display void");

                // 根据间隔时间保存图像
                auto time_now = std::chrono::system_clock::now();
                std::time_t timestamp_now = std::chrono::system_clock::to_time_t(time_now);
                std::time_t time_elapsed = timestamp_now - this->time_last_save;

                if (time_elapsed < 0){
                    THROW_EXCEPTION(std::runtime_error, "Collection Image Error (Time Elapsed)");
                    return;
                }

                if (time_elapsed < 5)
                    continue;

                // 时间间隔大于等于1秒，启动线程保存一帧
                 std::thread save_thread(&CameraController::save_image, this, image_data, timestamp_now, width, height, 8, PNG_COLOR_TYPE_RGB);
                save_thread.detach();  // 启动一个新的线程保存图像
                this->time_last_save = timestamp_now;

                // 非阻塞检查异常是否发生
                {
                    std::unique_lock<std::mutex> lock(this->mtx);
                    if (cv.wait_for(lock, std::chrono::milliseconds(0), [this] { return this->error_occurred; })) {
                        // 捕获到异常，处理错误信息
                        THROW_EXCEPTION(std::runtime_error, "Collection Image Error (Save Image)");
                        error_occurred = false;  // 重置错误标志
                    }
                }


            }


        }

        void CameraController::save_image(unsigned char *data_image, std::time_t timestamp_collection, int width, int height, int bit_depth, int color_type){
            try{
                LOG_INFO("Saving a frame image");
                this->image_saver.save_image_as_png(data_image, timestamp_collection, width, height, bit_depth, color_type);
                LOG_INFO("Saved a frame image");
                
            }catch(const std::exception& error){
                std::lock_guard<std::mutex> lock(this->mtx);
                this->error_occurred = true;
                this->error_message = error.what();
                this->cv.notify_one();
            }
        }


        CameraController::~CameraController(){
            g_clear_object(&this->camera);
        }


    } // namespace Camera
    
} // namespace DataCollection





